using Behaving.Composites;
using Behaving.Decorators;

namespace Behaving
{
    public static class BehaviourTreeReshaper
    {
        public static bool ReplaceBehaviour(BehaviourTree behaviourTree, string behaviourName, Behaviour behaviourToInsert)
        {
            if (behaviourTree.Root == null)
            {
                return false;
            }

            bool replaced = false;
            if (behaviourTree.Root.Name == behaviourName)
            {
                behaviourTree.Root = behaviourToInsert;
                replaced = true;
            }
            else
            {
                behaviourTree.Root.WalkTree(
                    b =>
                    {
                        if (ReplaceChildBehaviour(b, behaviourName, behaviourToInsert))
                        {
                            replaced = true;
                        }
                    });
            }
            return replaced;
        }

        private static bool ReplaceChildBehaviour(Behaviour behaviour, string behaviourName, Behaviour behaviourToInsert)
        {
            if (behaviour is Composite)
            {
                return ReplaceCompositeChildBehaviour(behaviour as Composite, behaviourName, behaviourToInsert);
            }

            if (behaviour is UtilitySelector)
            {
                return ReplaceUtilitySelectorChildBehaviour(behaviour as UtilitySelector, behaviourName, behaviourToInsert);
            }

            if (behaviour is Decorator)
            {
                return ReplaceDecoratorBehaviour(behaviour as Decorator, behaviourName, behaviourToInsert);
            }

            return false;
        }

        private static bool ReplaceDecoratorBehaviour(Decorator decorator, string behaviourName, Behaviour behaviourToInsert)
        {
            if (decorator.Behaviour.Name == behaviourName)
            {
                decorator.Behaviour = behaviourToInsert;
                return true;
            }
            return false;
        }

        private static bool ReplaceCompositeChildBehaviour(Composite composite, string behaviourName, Behaviour behaviour)
        {
            bool replaced = false;
            for (int index = 0; index < composite.Children.Count; index++)
            {
                if (composite.Children[index].Name == behaviourName)
                {
                    composite.Children[index] = behaviour;
                    replaced = true;
                }
            }

            return replaced;
        }

        private static bool ReplaceUtilitySelectorChildBehaviour(UtilitySelector utilitySelector, string behaviourName, Behaviour behaviour)
        {
            bool replaced = false;
            for (int index = 0; index < utilitySelector.Children.Count; index++)
            {
                if (utilitySelector.Children[index].Behaviour.Name == behaviourName)
                {
                    utilitySelector.Children[index].Behaviour = behaviour;
                    replaced = true;
                }
            }

            return replaced;
        }
    }
}